/**
 * @file KEYS.c
 * @brief 按键驱动文件
 * @details 实现按键的初始化、反初始化、外部中断处理等功能
 * @author 开发者
 * @date 创建日期
 */

#include "KEYS.h"

/* 外部队列句柄声明 */
extern QueueHandle_t  TRK_TRP_Stust;    // 轨迹航点状态队列
extern QueueHandle_t EXTI_AND_TIMER;    // 外部中断和定时器队列
/**
 * @brief 按键初始化函数
 * @details 配置按键GPIO为输入模式，使能外部中断，设置中断优先级
 */
void keys_init(void)
{
    rcu_periph_clock_enable(KEYS_RCU);  // 使能按键GPIO时钟
    
    /* 配置按键GPIO为输入模式，上拉 */
    gpio_mode_set(KEYS_PORT, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, KEY1_PIN | KEY2_PIN | KEY3_PIN | KEY4_PIN);
    
    exti_deinit();                      // 反初始化外部中断
    rcu_periph_clock_enable(RCU_SYSCFG); // 使能系统配置时钟
    
    /* 配置KEY1外部中断 */
    syscfg_exti_line_config(EXTI_SOURCE_GPIOC, EXTI_SOURCE_PIN0);  // 配置外部中断源
    exti_init(EXTI_0, EXTI_INTERRUPT, EXTI_TRIG_RISING);           // 初始化外部中断，上升沿触发
    nvic_irq_enable(EXTI0_IRQn, 6, 0);                             // 使能NVIC中断，优先级6
    exti_interrupt_enable(EXTI_0);                                 // 使能外部中断
    exti_interrupt_flag_clear(EXTI_0);                             // 清除中断标志

    /* 配置KEY2外部中断 */
    syscfg_exti_line_config(EXTI_SOURCE_GPIOC, EXTI_SOURCE_PIN1);  // 配置外部中断源
    exti_init(EXTI_1, EXTI_INTERRUPT, EXTI_TRIG_RISING);           // 初始化外部中断，上升沿触发
    nvic_irq_enable(EXTI1_IRQn, 6, 0);                             // 使能NVIC中断，优先级6
    exti_interrupt_enable(EXTI_1);                                 // 使能外部中断
    exti_interrupt_flag_clear(EXTI_1);                             // 清除中断标志

    /* 配置KEY3外部中断 */
    syscfg_exti_line_config(EXTI_SOURCE_GPIOC, EXTI_SOURCE_PIN2);  // 配置外部中断源
    exti_init(EXTI_2, EXTI_INTERRUPT, EXTI_TRIG_RISING);           // 初始化外部中断，上升沿触发
    nvic_irq_enable(EXTI2_IRQn, 6, 0);                             // 使能NVIC中断，优先级6
    exti_interrupt_enable(EXTI_2);                                 // 使能外部中断
    exti_interrupt_flag_clear(EXTI_2);                             // 清除中断标志

    /* 配置KEY4外部中断 */
    syscfg_exti_line_config(EXTI_SOURCE_GPIOC, EXTI_SOURCE_PIN3);  // 配置外部中断源
    exti_init(EXTI_3, EXTI_INTERRUPT, EXTI_TRIG_RISING);           // 初始化外部中断，上升沿触发
    nvic_irq_enable(EXTI3_IRQn, 6, 0);                             // 使能NVIC中断，优先级6
    exti_interrupt_enable(EXTI_3);                                 // 使能外部中断
    exti_interrupt_flag_clear(EXTI_3);                             // 清除中断标志
}

/**
 * @brief 按键反初始化函数
 * @details 禁用所有按键的外部中断
 */
void keys_deinit(){
    exti_interrupt_disable(EXTI_0 | EXTI_1 | EXTI_2 | EXTI_3);  // 禁用所有按键外部中断
}

/**
 * @brief KEY1外部中断服务函数
 * @details 处理KEY1按键按下事件，通过队列发送不同的状态值
 */
void EXTI0_IRQHandler(void) {
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;  // 高优先级任务唤醒标志
    static uint8_t send_num = 0;                    // 发送的状态值
    static uint8_t flag = 0;                        // 按键状态标志
    
    if(exti_interrupt_flag_get(EXTI_0) == 1)        // 检查中断标志
    {
        printf("exti 1");                           // 打印调试信息
        
        if(flag == 0) {
            printf("exti send 10\n");               // 打印调试信息
            send_num = 10;                          // 设置状态值为10
            xQueueSendFromISR( EXTI_AND_TIMER, &send_num, &xHigherPriorityTaskWoken );  // 从ISR发送队列
            if( xHigherPriorityTaskWoken ) {
                /* 实际使用的宏是端口特定的 */
                portYIELD_FROM_ISR (xHigherPriorityTaskWoken);  // 从ISR进行任务切换
            }
            flag = 1;                               // 设置标志位
        } else {
            printf("exti send 20\n");               // 打印调试信息
            send_num = 20;                          // 设置状态值为20
            xQueueSendFromISR( EXTI_AND_TIMER, &send_num, &xHigherPriorityTaskWoken );  // 从ISR发送队列
            if( xHigherPriorityTaskWoken ) {
                /* 实际使用的宏是端口特定的 */
                portYIELD_FROM_ISR (xHigherPriorityTaskWoken);  // 从ISR进行任务切换
            }
            flag = 0;                               // 清除标志位
        }

        exti_interrupt_flag_clear(EXTI_0);          // 清除中断标志
    }
}
/**
 * @brief KEY2外部中断服务函数
 * @details 暂时未完成KEY2按键功能
 */
void EXTI1_IRQHandler(void) {
    BaseType_t  xHigherPriorityTaskWoken = pdFALSE;  // 高优先级任务唤醒标志
    if(exti_interrupt_flag_get(EXTI_1) == 1)         // 检查中断标志
    {
        // TODO: 实现KEY2按键功能
    }
}

/**
 * @brief KEY3外部中断服务函数
 * @details 暂时未完成KEY3按键功能
 */
void EXTI2_IRQHandler(void) {
    BaseType_t  xHigherPriorityTaskWoken = pdFALSE;  // 高优先级任务唤醒标志
    if(exti_interrupt_flag_get(EXTI_2) == 1)         // 检查中断标志
    {
        // TODO: 实现KEY3按键功能
    }
}

/**
 * @brief KEY4外部中断服务函数
 * @details 暂时未完成KEY4按键功能
 */
void EXTI3_IRQHandler(void) {
    BaseType_t  xHigherPriorityTaskWoken = pdFALSE;  // 高优先级任务唤醒标志
    if(exti_interrupt_flag_get(EXTI_3) == 1)         // 检查中断标志
    {
        // TODO: 实现KEY4按键功能
        exti_interrupt_flag_clear(EXTI_3);           // 清除中断标志
    }
}